package pseudoAssemblerCompiler.twopassassembler.view.windows;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import pseudoAssemblerCompiler.twopassassembler.controller.OperationCodeController;
import pseudoAssemblerCompiler.twopassassembler.exceptions.RequiredDataNotSetException;
import pseudoAssemblerCompiler.twopassassembler.view.util.AttributeEditorComboLine;
import pseudoAssemblerCompiler.twopassassembler.view.util.SmartCombo;

/**
 * User: Роман
 * Date: 22.03.12
 * Time: 18:16
 */
public abstract class AbstractWindow implements Window {

    /**
     * Ширина модального окна
     */
    private static final int WINDOW_WIDTH = 1000;

    /**
     * Высота модального окна
     */
    private static final int WINDOW_HEIGHT = 200;

    /**
     * Отдельный Shell для диалогового окна
     */
    private Shell _shell;

    /**
     * Название модального окна
     */
    private String _nameOfWindow;

    /**
     * Тип условия
     */
    protected AttributeEditorComboLine _smthType;

    /**
     * Значение
     */
    protected AttributeEditorComboLine _value;

    /**
     * Название команды
     */
    protected AttributeEditorComboLine _mnemonicCode;

    public static final String MNEMONIC_CODE = "МКОП";

    /**
     * Двоичный код
     */
    protected AttributeEditorComboLine _binaryCode;

    public static final String BINARY_CODE = "Двоичный код";

    /**
     * Длина команды
     */
    protected AttributeEditorComboLine _commandLength;

    public static final String LENGTH_OF_COMMAND = "Длина команды";

    /**
     * Тип адресации
     */
    protected AttributeEditorComboLine _addressingType;

    public static final String TYPE_OF_ADDRESSING = "Тип адресации";

    /**
     * Директива или нет
     */
    protected AttributeEditorComboLine _directive;

    public static final String DIRECTIVE = "Директива";

    private Button _add;

    private Button _cancel;

    /**
     * Контроллер для вкладки редактора регламента опроса
     */
    protected OperationCodeController codeOperationController;

    public AbstractWindow(Display aDisplay, String aNameOfWindow) {
        _nameOfWindow = aNameOfWindow;
        _shell = new Shell(aDisplay, SWT.TITLE | SWT.BORDER);
    }

    @Override
    public void setController(Object aController) {
        if (aController instanceof OperationCodeController) {
            codeOperationController = (OperationCodeController) aController;
        }
    }

    protected SmartCombo getComboViewerForTypes() {
        return _smthType.getComboViewer();
    }

    protected SmartCombo getComboViewerForValue() {
        return _value.getComboViewer();
    }

    protected Shell getShell() {
        return _shell;
    }

    private void mainLayout() {
        _shell.setLayout(new FormLayout());
        FormData formData;

        formData = new FormData();
        formData.left = new FormAttachment(0, 0);
        formData.top = new FormAttachment(0, 0);
        formData.right = new FormAttachment(100, 0);
        formData.bottom = new FormAttachment(100, 0);
        _shell.setLayoutData(formData);

        //Тип атрибута опроса
        formData = new FormData();
        formData.left = new FormAttachment(0, 20);
        //formData.top = new FormAttachment(0, 20);
        formData.right = new FormAttachment(100, 0);
        formData.bottom = new FormAttachment(_add, -50);
        formData.height = 40;
        _mnemonicCode.setLayout(new FormLayout());
        _mnemonicCode.setLayoutData(formData);

        //Наименование
        formData = new FormData();
        formData.left = new FormAttachment(0, 20);
        //formData.top = new FormAttachment(0, 50);
        formData.right = new FormAttachment(100, 0);
        formData.bottom = new FormAttachment(_add, -10);
        formData.height = 40;
        _binaryCode.setLayout(new FormLayout());
        _binaryCode.setLayoutData(formData);

        //Наименование
        formData = new FormData();
        formData.left = new FormAttachment(0, 20);
        //formData.top = new FormAttachment(0, 50);
        formData.right = new FormAttachment(100, 0);
        formData.bottom = new FormAttachment(_add, -10);
        formData.height = 40;
        _commandLength.setLayout(new FormLayout());
        _commandLength.setLayoutData(formData);

        //Наименование
        formData = new FormData();
        formData.left = new FormAttachment(0, 20);
        //formData.top = new FormAttachment(0, 50);
        formData.right = new FormAttachment(100, 0);
        formData.bottom = new FormAttachment(_add, -10);
        formData.height = 40;
        _addressingType.setLayout(new FormLayout());
        _addressingType.setLayoutData(formData);

        //Наименование
        formData = new FormData();
        formData.left = new FormAttachment(0, 20);
        //formData.top = new FormAttachment(0, 50);
        formData.right = new FormAttachment(100, 0);
        formData.bottom = new FormAttachment(_add, -10);
        formData.height = 40;
        _directive.setLayout(new FormLayout());
        _directive.setLayoutData(formData);

        formData = new FormData();
        //formData.left = new FormAttachment(0, 0);
        //formData.top = new FormAttachment(0, 100);
        formData.right = new FormAttachment(_cancel, -10);
        formData.bottom = new FormAttachment(100, -20);
        formData.width = 100;
        formData.height = 30;
        _add.setLayoutData(formData);

        formData = new FormData();
        //formData.left = new FormAttachment(_add, 0);
        //formData.top = new FormAttachment(_value.getComboViewerForTypes().getControl(), 0);
        formData.right = new FormAttachment(100, -20);
        formData.bottom = new FormAttachment(100, -20);
        formData.width = 100;
        formData.height = 30;
        _cancel.setLayoutData(formData);
    }

    private void commonListeners() {
        _cancel.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetSelected(SelectionEvent selectionEvent) {
                getShell().dispose();
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent selectionEvent) {
                //To change body of implemented methods use File | Settings | File Templates.
            }
        });

        _add.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetSelected(SelectionEvent selectionEvent) {
                try {
                    saveButtonTriggered();
                    getShell().dispose();
                } catch (RequiredDataNotSetException e) {
                    makeMessage(e.getMessage());
                    _value.getComboViewer().getControl().setFocus();
                }
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent selectionEvent) {
                //To change body of implemented methods use File | Settings | File Templates.
            }
        });
    }

    protected abstract String getNameForType();

    protected abstract String[] getInputForType();

    protected abstract String[] getInputForValue();

    protected abstract void createContents();

    protected abstract void layout();

    protected abstract void listeners();

    protected abstract void saveButtonTriggered() throws RequiredDataNotSetException;

    protected abstract int getStyleForType();

    protected abstract int getStyleForValue();

    @Override
    public void create() {
        _shell.setLocation(_shell.getDisplay().getActiveShell().getLocation().x + getIncrement(true),
                _shell.getDisplay().getActiveShell().getLocation().y + getIncrement(false));
        _shell.setText(_nameOfWindow);
        _shell.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);

        _mnemonicCode = new AttributeEditorComboLine(_shell, MNEMONIC_CODE);
        _mnemonicCode.createText(SWT.NONE, SWT.BORDER);

        _binaryCode = new AttributeEditorComboLine(_shell, BINARY_CODE);
        _binaryCode.createComboLine(SWT.NONE, SWT.BORDER | SWT.READ_ONLY);

        _commandLength = new AttributeEditorComboLine(_shell, LENGTH_OF_COMMAND);
        _commandLength.createComboLine(SWT.NONE, SWT.BORDER | SWT.READ_ONLY);

        _addressingType = new AttributeEditorComboLine(_shell, TYPE_OF_ADDRESSING);
        _addressingType.createComboLine(SWT.NONE, SWT.BORDER | SWT.READ_ONLY);

        _directive = new AttributeEditorComboLine(_shell, DIRECTIVE);
        _directive.createComboLine(SWT.NONE, SWT.BORDER | SWT.READ_ONLY);

        _add = new Button(_shell, SWT.PUSH);
        _add.setText("Добавить");

        _cancel = new Button(_shell, SWT.PUSH);
        _cancel.setText("Отмена");

        createContents();
        mainLayout();
        commonListeners();
        layout();
        listeners();

        getShell().open(); //Открываем наше окошко=)
    }

    /**
     * Возвращает отступ модального окна от левого верхнего угла основного
     *
     * @param isWidth true - если приращение расчитывается для ширины
     * @return приращение
     */
    private int getIncrement(boolean isWidth) {
        int d;
        if (isWidth) {
            d = (_shell.getDisplay().getActiveShell().getBounds().width - WINDOW_WIDTH) / 2;
        } else {
            d = (_shell.getDisplay().getActiveShell().getBounds().height - WINDOW_HEIGHT) / 2;
        }
        return d;
    }

    /**
     * Сообщения при ошибках
     *
     * @param aMsg сообщение
     */
    private void makeMessage(String aMsg) {
        MessageBox messageBox;
        messageBox = new MessageBox(_shell, SWT.ICON_INFORMATION | SWT.YES);
        messageBox.setMessage(aMsg);
        messageBox.open();
    }
}
